home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / OS / FWGraphx / SLRegion.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  26.3 KB  |  940 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLRegion.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWErrors.h"
  11.  
  12. #include "FWOS.hpp"
  13.  
  14. #ifndef SLREGION_H
  15. #include "SLRegion.h"
  16. #endif
  17.  
  18. #ifndef FWFXMATH_H
  19. #include "FWFxMath.h"
  20. #endif
  21.  
  22. #ifndef FWRECT_H
  23. #include "FWRect.h"
  24. #endif
  25.  
  26. #ifndef FWPOINT_H
  27. #include "FWPoint.h"
  28. #endif
  29.  
  30. #ifndef SLGRGLOB_H
  31. #include "SLGrGlob.h"
  32. #endif
  33.  
  34. #ifndef PRGRUTIL_H
  35. #include "PRGrUtil.h"
  36. #endif
  37.  
  38. #ifndef FWPRIDEB_H
  39. #include "FWPriDeb.h"
  40. #endif
  41.  
  42. #ifndef FWSTRMRW_H
  43. #include "FWStrmRW.h"
  44. #endif
  45.  
  46. #ifndef FWMEMHLP_H
  47. #include "FWMemHlp.h"
  48. #endif
  49.  
  50. #ifndef FWMEMMGR_H
  51. #include "FWMemMgr.h"
  52. #endif
  53.  
  54. #ifdef FW_BUILD_MAC
  55. #pragma segment FWGraphx_Region
  56. #endif
  57.  
  58. //========================================================================================
  59. //    Local helpers
  60. //========================================================================================
  61.  
  62. #ifdef FW_BUILD_MAC
  63. static GrafPtr        PrivMacOpenRegion();
  64. static ODRgnHandle    PrivMacCloseRegion(GrafPtr svPort);
  65. #endif
  66.  
  67. #ifdef FW_BUILD_WIN
  68. static void PrivWinInsetRegionRectangle(LPPOINT lppt, int dx, int dy, const POINT& ptCenter);
  69. static void PrivWinInsetRegionRectangle(LPRECT lpRect, int dx, int dy, const POINT& ptCenter);
  70. #endif
  71.  
  72. //========================================================================================
  73. //    Region functions
  74. //========================================================================================
  75.  
  76. //----------------------------------------------------------------------------------------
  77. //    FW_CreateRectRegion
  78. //----------------------------------------------------------------------------------------
  79.  
  80. ODRgnHandle SL_API    FW_CreateRectRegion(const FW_SRect& rect)
  81. {
  82.     // No try block necessary - Do not throw
  83.     FW_CPlatformRect plfmRect = rect;
  84.     
  85. #ifdef FW_BUILD_MAC
  86.     ODRgnHandle rgn = ::FW_NewRegion();
  87.     ::RectRgn(rgn, &plfmRect);
  88.     return rgn;
  89. #endif
  90. #ifdef FW_BUILD_WIN
  91.     return ::CreateRectRgnIndirect(&plfmRect);
  92. #endif
  93. }
  94.  
  95. //----------------------------------------------------------------------------------------
  96. //    FW_CreateOvalRegion
  97. //----------------------------------------------------------------------------------------
  98.  
  99. ODRgnHandle SL_API    FW_CreateOvalRegion(const FW_SRect& rect)
  100. {
  101.     // No try block necessary - Do not throw
  102.     FW_CPlatformRect plfmRect(rect);
  103.  
  104. #ifdef FW_BUILD_MAC
  105.     GrafPtr svPort = PrivMacOpenRegion();
  106.     ::FrameOval(&plfmRect);
  107.     return PrivMacCloseRegion(svPort);
  108. #endif
  109.  
  110. #ifdef FW_BUILD_WIN
  111.     return ::CreateEllipticRgnIndirect(&plfmRect);
  112. #endif
  113. }
  114.  
  115. //----------------------------------------------------------------------------------------
  116. //    FW_CreateRoundRectRegion
  117. //----------------------------------------------------------------------------------------
  118.  
  119. ODRgnHandle SL_API    FW_CreateRoundRectRegion(const FW_SRect& rect, const FW_SPoint& ovalSize)
  120. {
  121.     // No try block necessary - Do not throw
  122.     FW_CPlatformRect plfmRect(rect);
  123.     FW_CPlatformPoint plfmPoint(ovalSize);
  124.  
  125. #ifdef FW_BUILD_MAC
  126.     GrafPtr svPort = PrivMacOpenRegion();
  127.     ::FrameRoundRect(&plfmRect, plfmPoint.X(), plfmPoint.Y());
  128.     return ::PrivMacCloseRegion(svPort);
  129. #endif
  130. #ifdef FW_BUILD_WIN
  131.     return ::CreateRoundRectRgn(plfmRect.left, plfmRect.top, 
  132.                                 plfmRect.right, plfmRect.bottom, 
  133.                                 plfmPoint.X(), plfmPoint.Y());
  134. #endif
  135. }
  136.  
  137. //----------------------------------------------------------------------------------------
  138. //    FW_CreateArcRegion
  139. //----------------------------------------------------------------------------------------
  140.  
  141. ODRgnHandle SL_API FW_CreateArcRegion(const FW_SRect& rect,
  142.                                       short startAngle, short arcAngle)
  143. {
  144.     // No try block necessary - Do not throw
  145.     // However, if a memory error occurs, we may return NULL!
  146.     
  147.     FW_CPlatformRect plfmRect(rect);
  148.  
  149.     // first, we make a polygon with the segmented arc a little outside of the tru arc
  150.     
  151.     const unsigned short enlargeFactor = 8; // magic number: we enlarge the rectangle
  152.     const short width = plfmRect.right - plfmRect.left;
  153.     const short height = plfmRect.bottom - plfmRect.top;
  154.     short outset = FW_FixedToInt(FW_Sqrt(FW_IntToFixed(width / enlargeFactor)));
  155.     
  156.     plfmRect.left -= outset;
  157.     plfmRect.right += outset;
  158.  
  159.     if(width != height)
  160.         outset = FW_FixedToInt(FW_Sqrt(FW_IntToFixed(height / enlargeFactor)));
  161.         
  162.     plfmRect.top -= outset;
  163.     plfmRect.bottom += outset;
  164.  
  165.     // normalize the starting point and arc angles for the coord system used by Quickdraw
  166.     
  167.     if (startAngle >= 360)
  168.         startAngle = startAngle % 360;
  169.     else if (startAngle < 0)
  170.         startAngle = (startAngle % 360) + 360;
  171.  
  172.     if (arcAngle > 360)
  173.         arcAngle = arcAngle % 360;
  174.     else if (arcAngle < 0)
  175.         arcAngle = (arcAngle % 360) + 360;
  176.     
  177.     // start with a new, empty region
  178.     ODRgnHandle hArcRegion = FW_NewRegion();
  179.     
  180.     if(arcAngle != 0)
  181.     {
  182.         const ODUShort kAnglePerSegment = 5; // one line segment for every kAnglePerSegment degrees
  183.         const ODUShort kMaxPoints = (360 / kAnglePerSegment) + 1; // max segments + 1
  184.         
  185.         ODUShort numSegments = arcAngle / kAnglePerSegment;
  186.  
  187.         ODUShort angle = startAngle;
  188.         
  189.         FW_SPoint pt[kMaxPoints + 1]; //  (numSegments + 1) points for the arc plus one for the center
  190.         for (ODUShort i = 0; i <= numSegments; i++) // we create numSegments +1 points for the arc
  191.         {
  192.             angle = startAngle + arcAngle * i / numSegments;
  193.             
  194.             FW_CPlatformPoint tempPt;
  195.             FW_PrivCalcArcPoints(plfmRect, angle, tempPt);
  196.             pt[i].x = FW_IntToFixed(tempPt.h);
  197.             pt[i].y = FW_IntToFixed(tempPt.v);
  198.         }
  199.  
  200.         // add the vertex to the array
  201.         pt[numSegments + 1].x = FW_Half(rect.left + rect.right);
  202.         pt[numSegments + 1].y = FW_Half(rect.top + rect.bottom);
  203.  
  204.         ODRgnHandle hPolygonRgn = ::FW_CreatePolygonRegion(numSegments + 2, pt);
  205.         
  206.         if(hPolygonRgn != NULL)
  207.         {
  208.             ODRgnHandle hEllipticRgn = FW_CreateOvalRegion(rect);
  209.             
  210.             #ifdef FW_BUILD_MAC
  211.                 ::SectRgn(hEllipticRgn, hPolygonRgn, hArcRegion);
  212.                 
  213.                 if(::QDError() != noErr)
  214.                 {
  215.                     FW_DisposeRegion(hArcRegion);
  216.                     hArcRegion = NULL;
  217.                 }
  218.                 
  219.             #endif
  220.             #ifdef FW_BUILD_WIN
  221.                 ::CombineRgn(hArcRegion, hEllipticRgn, hPolygonRgn, RGN_AND);
  222.             #endif
  223.  
  224.             FW_DisposeRegion(hEllipticRgn);
  225.         }
  226.         
  227.         FW_DisposeRegion(hPolygonRgn);
  228.     }
  229.     
  230.     // Return the result
  231.     return hArcRegion;
  232. }
  233.  
  234.  
  235. #ifdef FW_BUILD_MAC
  236.  
  237. //----------------------------------------------------------------------------------------
  238. //    FW_PrivMacDrawPolyPoints
  239. //----------------------------------------------------------------------------------------
  240.  
  241. inline void FW_PrivMacDrawPolyPoints(unsigned long pointCount, const FW_SPoint* pointArray, Boolean closed)
  242. {
  243.     FW_CPlatformPoint startPt = pointArray[0];
  244.     FW_CPlatformPoint lastPt = startPt;
  245.     FW_CPlatformPoint pt;
  246.  
  247.     ::MoveTo(startPt.h, startPt.v);
  248.     
  249.     for(unsigned long i = 1; i < pointCount; i ++)
  250.     {
  251.         pt = pointArray[i];
  252.         if(pt != lastPt)
  253.         {
  254.             lastPt = pt;
  255.             ::LineTo(pt.h, pt.v);
  256.         }
  257.     }
  258.     
  259.     if(closed && (startPt != pt))
  260.         ::LineTo(startPt.h, startPt.v);
  261. }
  262.  
  263. #endif
  264.  
  265. //----------------------------------------------------------------------------------------
  266. //    FW_CreatePolygonRegion
  267. //----------------------------------------------------------------------------------------
  268.  
  269. ODRgnHandle SL_API    FW_CreatePolygonRegion(unsigned long pointCount, const FW_SPoint* pointArray)
  270. {
  271.     // No try block necessary - Do not throw
  272. #ifdef FW_BUILD_MAC
  273.     GrafPtr savePort = ::PrivMacOpenRegion();
  274.     
  275.     FW_PrivMacDrawPolyPoints(pointCount, pointArray, true);
  276.     
  277.     ODRgnHandle resultRgn = ::PrivMacCloseRegion(savePort);
  278.  
  279.     return resultRgn;
  280. #endif
  281. #ifdef FW_BUILD_WIN
  282.     FW_CPlatformPoint* points = new FW_CPlatformPoint[pointCount];
  283.     
  284.     for(unsigned long i = 0; i < pointCount; i ++)
  285.         points[i] = pointArray[i];
  286.  
  287.     HRGN hRgn = ::CreatePolygonRgn(points, pointCount, ALTERNATE);
  288.     delete[] points;
  289.     
  290.     return hRgn;
  291. #endif
  292. }
  293.  
  294. //----------------------------------------------------------------------------------------
  295. //    FW_CreateLineRegion
  296. //----------------------------------------------------------------------------------------
  297.  
  298. ODRgnHandle SL_API    FW_CreateLineRegion(const FW_SPoint& startPt,
  299.                                              const FW_SPoint& endPt,
  300.                                              const FW_SPoint& lineThickness)
  301. {
  302.     // No try block necessary - Do not throw
  303.     ODRgnHandle rgn;
  304.     
  305.     FW_CPlatformPoint firstPoint(startPt);
  306.     FW_CPlatformPoint lastPoint(endPt);
  307.     FW_CPlatformPoint penSize(lineThickness);
  308.     
  309.     FW_CPlatformRect halfPen(-penSize.X() / 2, -penSize.Y() / 2, (penSize.X() + 1) / 2, (penSize.Y() + 1) / 2);
  310.  
  311.     FW_CPlatformRect rect(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top, firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  312.  
  313.     short regionCode = 0;
  314.     if (lastPoint.X() < rect.left)
  315.         regionCode = 0x0008;
  316.     else if (lastPoint.X() > rect.right)
  317.         regionCode = 0x0004;
  318.     
  319.     if (lastPoint.Y() < rect.top)
  320.         regionCode |= 0x0001;
  321.     else if (lastPoint.Y() > rect.bottom)
  322.         regionCode |= 0x0002;
  323.  
  324.     short nbPoint;
  325.     FW_CPlatformPoint pt[6];
  326.     
  327.     switch (regionCode)
  328.     {
  329.         case 0x0000:
  330.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  331.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  332.             nbPoint = 2;
  333.             break;
  334.         case 0x0004:
  335.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  336.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  337.             nbPoint = 2;
  338.             break;
  339.         case 0x0008:
  340.             pt[0].Set(lastPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  341.             pt[1].Set(firstPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  342.             nbPoint = 2;
  343.             break;
  344.         case 0x0002:
  345.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  346.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  347.             nbPoint = 2;
  348.             break;
  349.         case 0x0001:
  350.             pt[0].Set(firstPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  351.             pt[1].Set(lastPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  352.             nbPoint = 2;
  353.             break;
  354.         case 0x0005:
  355.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  356.             pt[1].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  357.             pt[2].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  358.             pt[3].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  359.             pt[4].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  360.             pt[5].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  361.             nbPoint = 6;
  362.             break;
  363.         case 0x0006:
  364.             pt[0].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  365.             pt[1].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  366.             pt[2].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  367.             pt[3].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  368.             pt[4].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  369.             pt[5].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  370.             nbPoint = 6;
  371.             break;
  372.         case 0x000A:
  373.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  374.             pt[1].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  375.             pt[2].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  376.             pt[3].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  377.             pt[4].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  378.             pt[5].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  379.             nbPoint = 6;
  380.             break;
  381.         case 0x0009:
  382.             pt[0].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  383.             pt[1].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  384.             pt[2].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  385.             pt[3].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  386.             pt[4].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  387.             pt[5].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  388.             nbPoint = 6;
  389.             break;
  390.     }
  391.     
  392. #ifdef FW_BUILD_WIN
  393.     if (nbPoint == 2)
  394.         rgn = ::CreateRectRgn(pt[0].x, pt[0].y, pt[1].x, pt[1].y);
  395.     else
  396.         rgn = ::CreatePolygonRgn(pt, nbPoint, WINDING);
  397. #endif        
  398.     
  399. #ifdef FW_BUILD_MAC
  400.     if (nbPoint == 2)
  401.     {
  402.         rgn = ::FW_NewRegion();
  403.         FW_CPlatformRect rect(pt[0], pt[1]);
  404.         ::RectRgn(rgn, &rect);
  405.     }
  406.     else
  407.     {
  408.         GrafPtr svPort = ::PrivMacOpenRegion();
  409.         ::MoveTo(pt[0].h, pt[0].v);
  410.         ::LineTo(pt[1].h, pt[1].v);
  411.         ::LineTo(pt[2].h, pt[2].v);            
  412.         ::LineTo(pt[3].h, pt[3].v);
  413.         ::LineTo(pt[4].h, pt[4].v);            
  414.         ::LineTo(pt[5].h, pt[5].v);
  415.         ::LineTo(pt[0].h, pt[0].v);
  416.         rgn = ::PrivMacCloseRegion(svPort);
  417.     }
  418. #endif
  419.  
  420.     return rgn;
  421. }
  422.  
  423. //----------------------------------------------------------------------------------------
  424. //    FW_CopyRegion
  425. //----------------------------------------------------------------------------------------
  426.  
  427. ODRgnHandle SL_API    FW_CopyRegion(ODRgnHandle scrRgn)
  428. {
  429.     // No try block necessary - Do not throw
  430.     FW_ASSERT(scrRgn != NULL);
  431.     
  432.     ODRgnHandle newRgn = ::FW_NewRegion();
  433.  
  434. #ifdef FW_BUILD_MAC
  435.     ::CopyRgn(scrRgn, newRgn);
  436. #endif
  437. #ifdef FW_BUILD_WIN
  438.     ::CombineRgn(newRgn, scrRgn, NULL, RGN_COPY);
  439. #endif
  440.  
  441.     return newRgn;
  442. }
  443.  
  444. //----------------------------------------------------------------------------------------
  445. //    FW_CopyRegionTo
  446. //----------------------------------------------------------------------------------------
  447.  
  448. void SL_API    FW_CopyRegionTo(ODRgnHandle scrRgn, ODRgnHandle dstRgn)
  449. {
  450.     // No try block necessary - Do not throw
  451.     FW_ASSERT(scrRgn != NULL);
  452.     FW_ASSERT(dstRgn != NULL);
  453.     
  454. #ifdef FW_BUILD_MAC
  455.     ::CopyRgn(scrRgn, dstRgn);
  456. #endif
  457. #ifdef FW_BUILD_WIN
  458.     ::CombineRgn(dstRgn, scrRgn, NULL, RGN_COPY);
  459. #endif
  460. }
  461.  
  462. //----------------------------------------------------------------------------------------
  463. //    FW_NewRegion
  464. //----------------------------------------------------------------------------------------
  465.  
  466. ODRgnHandle SL_API    FW_NewRegion()
  467. {    
  468.     // No try block necessary - Do not throw
  469. #ifdef FW_BUILD_MAC
  470.     ODRgnHandle r;
  471.     FW_TRY
  472.     {
  473.         r = (ODRgnHandle)FW_CMemoryManager::AllocateSystemHandle(sizeof(Region));
  474.     }
  475.     FW_CATCH_BEGIN
  476.     FW_CATCH_EVERYTHING()
  477.     {
  478.         return NULL;
  479.     }
  480.     FW_CATCH_END
  481.     (**r).rgnSize = sizeof(Region);
  482.     SetRect(&(**r).rgnBBox, 0,0,0,0);
  483.     return r;
  484. #endif
  485.  
  486. #ifdef FW_BUILD_WIN
  487.     return ::CreateRectRgn(0,0,0,0);
  488. #endif
  489. }
  490.  
  491. //----------------------------------------------------------------------------------------
  492. //    FW_DisposeRegion
  493. //----------------------------------------------------------------------------------------
  494.  
  495. void SL_API    FW_DisposeRegion(ODRgnHandle rgn)
  496. {
  497.     // No try block necessary - Do not throw
  498.     FW_ASSERT(rgn != 0);
  499.     
  500. #ifdef FW_BUILD_MAC
  501.     FW_CMemoryManager::FreeSystemHandle((FW_PlatformHandle)rgn);
  502. #endif
  503. #ifdef FW_BUILD_WIN
  504.     ::DeleteObject(rgn);
  505. #endif
  506. }
  507.  
  508. //----------------------------------------------------------------------------------------
  509. //    FW_OutlineRegion
  510. //----------------------------------------------------------------------------------------
  511.  
  512. void SL_API    FW_OutlineRegion(ODRgnHandle rgn, FW_Fixed outlineSize)
  513. {
  514.     ODRgnHandle tempRgn = ::FW_CopyRegion(rgn);
  515.     
  516.     if (outlineSize <= FW_kFixed0)
  517.         outlineSize = FW_kFixedPos1;
  518.     
  519.     ::FW_InsetRegion(tempRgn, outlineSize, outlineSize);
  520.     
  521. #ifdef FW_BUILD_MAC
  522.     ::DiffRgn(rgn, tempRgn, rgn);
  523. #endif
  524. #ifdef FW_BUILD_WIN
  525.     ::CombineRgn(rgn, rgn, tempRgn, RGN_DIFF);
  526. #endif
  527.  
  528.     ::FW_DisposeRegion(tempRgn);
  529. }
  530.  
  531. //----------------------------------------------------------------------------------------
  532. //    FW_InsetRegion
  533. //----------------------------------------------------------------------------------------
  534.  
  535. void SL_API    FW_InsetRegion(ODRgnHandle rgn, FW_Fixed x, FW_Fixed y)
  536. {
  537.     // No try block necessary - Do not throw
  538. #ifdef FW_BUILD_MAC
  539.     ::InsetRgn(rgn, FW_FixedToInt(x), FW_FixedToInt(y));
  540. #endif
  541. #ifdef FW_BUILD_WIN
  542.     int dx = FW_FixedToInt(x);
  543.     int dy = FW_FixedToInt(y);
  544.     
  545.     if (dx == 0 && dy == 0)
  546.         return;
  547.  
  548.     // Note: This code relies on partially documented Windows GDI data structures!
  549.  
  550.     // Get the current region data
  551.     long size = ::GetRegionData(rgn, 0, NULL);
  552.     
  553.     FW_CAcquireTemporaryMemory tempMem(size);
  554.     LPRGNDATA rgnData = (LPRGNDATA) tempMem.GetPointer();
  555.     ::GetRegionData(rgn, size, rgnData);
  556.     
  557.     // Massage the region data
  558.     if(rgnData->rdh.iType == RDH_RECTANGLES)
  559.     {
  560.         POINT ptCenter;
  561.         ptCenter.x = (rgnData->rdh.rcBound.left + rgnData->rdh.rcBound.right) / 2;
  562.         ptCenter.y = (rgnData->rdh.rcBound.top  + rgnData->rdh.rcBound.bottom) / 2;
  563.         
  564.         LPRECT lpRect = (LPRECT) rgnData->Buffer;
  565.  
  566.         for(unsigned long i = 0; i < rgnData->rdh.nCount; ++ i, ++ lpRect)
  567.             ::PrivWinInsetRegionRectangle(lpRect, dx, dy, ptCenter);
  568.     }
  569.  
  570.     // Create a new region and replace the one passed in    
  571.     HRGN hNewRgn = ::ExtCreateRegion(NULL, size, rgnData);
  572.     if(hNewRgn == NULL)
  573.         FW_Failure(FW_xMemoryExhausted);
  574.  
  575.     ::FW_CopyRegionTo(hNewRgn, rgn);
  576.     ::FW_DisposeRegion(hNewRgn);
  577. #endif
  578. }
  579.  
  580. //----------------------------------------------------------------------------------------
  581. //    FW_MapRegion
  582. //----------------------------------------------------------------------------------------
  583.  
  584. void SL_API    FW_MapRegion(ODRgnHandle rgn, const FW_SRect& srcRect, const FW_SRect& dstRect)
  585. {
  586.     // No try block necessary - Do not throw
  587.     FW_CPlatformRect plfmSrc(srcRect);
  588.     FW_CPlatformRect plfmDst(dstRect);
  589.     
  590. #ifdef FW_BUILD_MAC
  591.     ::MapRgn(rgn, &plfmSrc, &plfmDst);
  592. #endif
  593. #ifdef FW_BUILD_WIN
  594.     // Get the current region data
  595.     long size = ::GetRegionData(rgn, 0, NULL);
  596.     
  597.     FW_CAcquireTemporaryMemory tempMem(size);
  598.     LPRGNDATA rgnData = (LPRGNDATA) tempMem.GetPointer();
  599.     ::GetRegionData(rgn, size, rgnData);
  600.  
  601.     // Figure out the desired transform
  602.     XFORM xform;
  603.     xform.eM11 = (float) FW_FixedToDouble((dstRect.right - dstRect.left) / (srcRect.right - srcRect.left));
  604.     xform.eM12 = 0.0f;
  605.     xform.eM21 = 0.0f;
  606.     xform.eM22 = (float) FW_FixedToDouble((dstRect.bottom - dstRect.top) / (srcRect.bottom - srcRect.top));
  607.     xform.eDx  = (float) FW_FixedToDouble(dstRect.left - srcRect.left);
  608.     xform.eDy  = (float) FW_FixedToDouble(dstRect.top  - srcRect.top);
  609.  
  610.     // Create a new region and replace the one passed in    
  611.     HRGN hNewRgn = ::ExtCreateRegion(&xform, size, rgnData);
  612.     if(hNewRgn == NULL)
  613.         FW_Failure(FW_xMemoryExhausted);
  614.  
  615.     ::FW_CopyRegionTo(hNewRgn, rgn);
  616.     ::FW_DisposeRegion(hNewRgn);
  617. #endif
  618. }
  619.  
  620. //----------------------------------------------------------------------------------------
  621. //    FW_EmptyRegion
  622. //----------------------------------------------------------------------------------------
  623.  
  624. void SL_API    FW_EmptyRegion(ODRgnHandle rgn)
  625. {
  626.     // No try block necessary - Do not throw
  627. #ifdef FW_BUILD_MAC
  628.     ::SetEmptyRgn(rgn);
  629. #endif
  630. #ifdef FW_BUILD_WIN
  631.     ::SetRectRgn(rgn, 0, 0, 0, 0);
  632. #endif
  633. }
  634.  
  635. //----------------------------------------------------------------------------------------
  636. //    FW_OffsetRegion
  637. //----------------------------------------------------------------------------------------
  638.  
  639. void SL_API    FW_OffsetRegion(ODRgnHandle rgn, FW_Fixed x, FW_Fixed y)
  640. {
  641.     ::OffsetRgn(rgn, FW_FixedToInt(x), FW_FixedToInt(y));
  642. }
  643.  
  644. //----------------------------------------------------------------------------------------
  645. //    FW_GetRegionBoundingBox
  646. //----------------------------------------------------------------------------------------
  647.  
  648. void SL_API    FW_GetRegionBoundingBox(ODRgnHandle rgn, FW_SRect& rect)
  649. {
  650.     // No try block necessary - Do not throw
  651. #ifdef FW_BUILD_MAC
  652.     rect = FW_CRect((*rgn)->rgnBBox);
  653. #endif
  654. #ifdef FW_BUILD_WIN
  655.     FW_CPlatformRect plfmRect;
  656.     ::GetRgnBox(rgn, &plfmRect);
  657.     rect = FW_CRect(plfmRect);
  658. #endif
  659. }
  660.  
  661. //----------------------------------------------------------------------------------------
  662. //    FW_PointInRegion
  663. //----------------------------------------------------------------------------------------
  664.  
  665. FW_Boolean SL_API    FW_PointInRegion(ODRgnHandle rgn, const FW_SPoint& point)
  666. {
  667.     // No try block necessary - Do not throw
  668.     FW_CPlatformPoint plfmPt = point;
  669. #ifdef FW_BUILD_MAC
  670.     return ::PtInRgn(plfmPt, rgn);
  671. #endif
  672. #ifdef FW_BUILD_WIN
  673.     return ::PtInRegion(rgn, plfmPt.X(), plfmPt.Y());
  674. #endif
  675. }
  676.  
  677. //----------------------------------------------------------------------------------------
  678. //    FW_RectInRegion
  679. //----------------------------------------------------------------------------------------
  680.  
  681. FW_Boolean SL_API    FW_RectInRegion(ODRgnHandle rgn, const FW_SRect& rect)
  682. {
  683.     // No try block necessary - Do not throw
  684.     FW_CPlatformRect plfmRect = rect;
  685. #ifdef FW_BUILD_MAC
  686.     return ::RectInRgn(&plfmRect, rgn);
  687. #endif
  688. #ifdef FW_BUILD_WIN
  689.     return ::RectInRegion(rgn, &plfmRect);
  690. #endif
  691. }
  692.  
  693. //----------------------------------------------------------------------------------------
  694. //    FW_IsEmptyRegion
  695. //----------------------------------------------------------------------------------------
  696.  
  697. FW_Boolean SL_API    FW_IsEmptyRegion(ODRgnHandle rgn)
  698. {
  699.     // No try block necessary - Do not throw
  700. #ifdef FW_BUILD_MAC
  701.     return ::EmptyRgn(rgn);
  702. #endif
  703. #ifdef FW_BUILD_WIN
  704.     return ::CombineRgn(rgn, rgn, rgn, RGN_AND) == NULLREGION;
  705. #endif
  706. }
  707.  
  708. #ifdef FW_BUILD_MAC
  709. //----------------------------------------------------------------------------------------
  710. //    PrivMacOpenRegion
  711. //----------------------------------------------------------------------------------------
  712.  
  713. static GrafPtr PrivMacOpenRegion()
  714. {
  715.     GrafPtr svPort;
  716.     ::GetPort(&svPort);
  717.     ::SetPort(FW_gScratchPort);
  718.     ::OpenRgn();
  719.     return svPort;
  720. }
  721. #endif
  722.  
  723. #ifdef FW_BUILD_MAC
  724. //----------------------------------------------------------------------------------------
  725. //    PrivMacCloseRegion
  726. //----------------------------------------------------------------------------------------
  727.  
  728. ODRgnHandle PrivMacCloseRegion(GrafPtr svPort)
  729. {
  730.     ODRgnHandle hRgn = ::FW_NewRegion();
  731.     ::CloseRgn(hRgn);
  732.     OSErr err = ::QDError();
  733.     if(err != noErr)
  734.     {
  735.         ::FW_DisposeRegion(hRgn);
  736.         hRgn = NULL;
  737.     }
  738.     ::SetPort(svPort);
  739.     return hRgn;
  740. }
  741. #endif
  742.  
  743. #ifdef FW_BUILD_WIN
  744.  
  745. //----------------------------------------------------------------------------------------
  746. //    PrivWinInsetRegionPoint
  747. //----------------------------------------------------------------------------------------
  748.  
  749. static void PrivWinInsetRegionRectangle(LPPOINT lppt, int dx, int dy, const POINT& ptCenter)
  750. {
  751.     if (lppt->x < ptCenter.x)
  752.     {
  753.         if ((lppt->x += dx) > ptCenter.x)
  754.             lppt->x = ptCenter.x;
  755.     }
  756.     else
  757.     {
  758.         if ((lppt->x -= dx) < ptCenter.x)
  759.             lppt->x = ptCenter.x;
  760.     }
  761.  
  762.     if (lppt->y < ptCenter.y)
  763.     {
  764.         if((lppt->y += dy) > ptCenter.y)
  765.             lppt->y = ptCenter.y;
  766.     }
  767.     else
  768.     {
  769.         if ((lppt->y -= dy) < ptCenter.y)
  770.             lppt->y = ptCenter.y;
  771.     }
  772. }
  773.  
  774. //----------------------------------------------------------------------------------------
  775. //    PrivWinInsetRegionRectangle
  776. //----------------------------------------------------------------------------------------
  777.  
  778. static void PrivWinInsetRegionRectangle(LPRECT lpRect, int dx, int dy, const POINT& ptCenter)
  779. {
  780.     PrivWinInsetRegionRectangle(((LPPOINT) lpRect) + 0, dx, dy, ptCenter);
  781.     PrivWinInsetRegionRectangle(((LPPOINT) lpRect) + 1, dx, dy, ptCenter);
  782. }
  783.  
  784. #endif
  785.  
  786. //----------------------------------------------------------------------------------------
  787. //    FW_WriteRegion
  788. //----------------------------------------------------------------------------------------
  789.  
  790. void SL_API FW_WriteRegion(ODRgnHandle rgnHandle, FW_HWritableStream hStream, FW_PlatformError* error)
  791. {
  792.     FW_ERR_TRY
  793.     {
  794.         FW_CWritableStream stream(hStream);
  795.     
  796. #ifdef FW_BUILD_WIN
  797.         long size = ::GetRegionData(rgnHandle, 0, NULL);
  798.         
  799.         FW_CAcquireTemporaryMemory tempMem(size);
  800.         LPRGNDATA rgnData = (LPRGNDATA) tempMem.GetPointer();
  801.         ::GetRegionData(rgnHandle, size, rgnData);
  802.         
  803.         stream << size;
  804.         stream.Write(rgnData, size);
  805. #endif
  806. #ifdef FW_BUILD_MAC
  807.         short size = (*rgnHandle)->rgnSize;
  808.         
  809.         FW_CAcquireLockedSystemHandle memHandle((FW_PlatformHandle)rgnHandle);
  810.         void* rgnData = memHandle.GetPointer();
  811.         
  812.         stream << size;
  813.         stream.Write(rgnData, size);
  814. #endif
  815.     }
  816.     FW_ERR_CATCH
  817. }
  818.  
  819. //----------------------------------------------------------------------------------------
  820. //    FW_ReadRegion
  821. //----------------------------------------------------------------------------------------
  822.  
  823. ODRgnHandle SL_API FW_ReadRegion(FW_HReadableStream hStream, FW_PlatformError* error)
  824. {
  825.     FW_ERR_TRY
  826.     {
  827.         FW_CReadableStream stream(hStream);
  828.     
  829. #ifdef FW_BUILD_WIN
  830.         long size;
  831.         stream >> size;
  832.         
  833.         FW_CAcquireTemporaryMemory tempMem(size);
  834.         LPRGNDATA rgnData = (LPRGNDATA) tempMem.GetPointer();
  835.         stream.Read(rgnData, size);
  836.     
  837.         return ::ExtCreateRegion(NULL, size, rgnData);
  838. #endif
  839. #ifdef FW_BUILD_MAC
  840.         short size;
  841.         stream >> size;
  842.         
  843.         FW_CAcquireTemporarySystemHandle memHandle(size);
  844.         void* rgnData = memHandle.GetPointer();
  845.         
  846.         stream.Read(rgnData, size);
  847.     
  848.         memHandle.Orphan();
  849.         return (ODRgnHandle) memHandle.GetPlatformHandle();
  850. #endif
  851.     }
  852.     FW_ERR_CATCH
  853.     return NULL;
  854. }
  855.  
  856. //----------------------------------------------------------------------------------------
  857. //    FW_UnionRegion
  858. //----------------------------------------------------------------------------------------
  859.  
  860. ODRgnHandle SL_API FW_UnionRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  861. {
  862.     // No try block necessary - Do not throw
  863.     ODRgnHandle dstRgn = ::FW_NewRegion();
  864.     if (dstRgn == NULL)
  865.         return NULL;
  866.     
  867. #ifdef FW_BUILD_MAC
  868.     ::UnionRgn(rgn1, rgn2, dstRgn);
  869. #endif
  870. #ifdef FW_BUILD_WIN
  871.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_OR);
  872. #endif
  873.  
  874.     return dstRgn;
  875. }
  876.  
  877. //----------------------------------------------------------------------------------------
  878. //    FW_XorRegion
  879. //----------------------------------------------------------------------------------------
  880.  
  881. ODRgnHandle SL_API FW_XorRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  882. {
  883.     // No try block necessary - Do not throw
  884.     ODRgnHandle dstRgn = ::FW_NewRegion();
  885.     if (dstRgn == NULL)
  886.         return NULL;
  887.         
  888. #ifdef FW_BUILD_MAC
  889.     ::XorRgn(rgn1, rgn2, dstRgn);
  890. #endif
  891. #ifdef FW_BUILD_WIN
  892.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_XOR);
  893. #endif
  894.  
  895.     return dstRgn;
  896. }
  897.  
  898. //----------------------------------------------------------------------------------------
  899. //    FW_SubtractRegion
  900. //----------------------------------------------------------------------------------------
  901.  
  902. ODRgnHandle SL_API FW_SubtractRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  903. {
  904.     // No try block necessary - Do not throw
  905.     ODRgnHandle dstRgn = ::FW_NewRegion();
  906.     if (dstRgn == NULL)
  907.         return NULL;
  908.     
  909. #ifdef FW_BUILD_MAC
  910.     ::DiffRgn(rgn1, rgn2, dstRgn);
  911. #endif
  912. #ifdef FW_BUILD_WIN
  913.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_DIFF);
  914. #endif
  915.  
  916.     return dstRgn;
  917. }
  918.  
  919. //----------------------------------------------------------------------------------------
  920. //    FW_IntersectRegion
  921. //----------------------------------------------------------------------------------------
  922.  
  923. ODRgnHandle SL_API FW_IntersectRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  924. {
  925.     // No try block necessary - Do not throw
  926.     ODRgnHandle dstRgn = ::FW_NewRegion();
  927.     if (dstRgn == NULL)
  928.         return NULL;
  929.     
  930. #ifdef FW_BUILD_MAC
  931.     ::SectRgn(rgn1, rgn2, dstRgn);
  932. #endif
  933. #ifdef FW_BUILD_WIN
  934.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_AND);
  935. #endif
  936.  
  937.     return dstRgn;
  938. }
  939.  
  940.